﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using System.Reflection;
using System.IO;
using Minestorm.Evolved.IoC;

namespace Minestorm.Evolved.Assets
{
    public class AssetManager : IAssetManager
    {
        private Dictionary<Textures, string> _textures = null;
        private Dictionary<Effects, string> _effects = null;
        private Dictionary<Fonts, string> _fonts = null;
        private Dictionary<Models, string> _models = null;

        private IObjectFactory _iocContainer;

        public AssetManager(IObjectFactory iocContainer)
        {
            _textures = Initialize<Textures>();
            _effects = Initialize<Effects>();
            _fonts = Initialize<Fonts>();
            _models = Initialize<Models>();

            _iocContainer = iocContainer;
        }

        public Texture2D Load(Textures texture)
        {
            return GetContent<Texture2D>(_textures[texture]);
        }

        public Effect Load(Effects effect)
        {
            var fx = GetContent<Effect>(_effects[effect]);
            fx.Name = effect.ToString();
            return fx;
        }

        public T Load<T>(Effects effect)
            where T : class, ICustomEffect
        {
            var fx = Load(effect);

            return (T)(object)fx;
        }

        public SpriteFont Load(Fonts font)
        {
            return GetContent<SpriteFont>(_fonts[font]);
        }

        public Model Load(Models model)
        {
            return GetContent<Model>(_models[model]);
        }

        private T GetContent<T>(string path)
        {
            var content = _iocContainer.InstanceOf<IContentManager>();

            return content.Load<T>(path);
        }

        public void Dispose()
        {
        }

        private Dictionary<T, string> Initialize<T>()
            where T : struct
        {
            var dic = new Dictionary<T, string>();

            var rootAtts = typeof(T).GetCustomAttributes(typeof(ContentRootAttribute), false);

            var root = rootAtts.Length == 0 ? "" : ((ContentRootAttribute)rootAtts[0]).Path;

            foreach (var field in typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                var pathAtts = field.GetCustomAttributes(typeof(ContentAttribute), false);

                var path = pathAtts.Length == 0 ? field.Name : ((ContentAttribute)pathAtts[0]).Path;

                dic.Add((T)field.GetValue(null), Path.Combine(root, path));
            }

            return dic;
        }
    }
}
